﻿//*****************************************************************************
//** Project:PatternWell.PAC
//** Copyright 2011 PatternWell LLC
//** Revision History:
//** Version 1.0 - Initial Release
//*****************************************************************************

using System;

namespace PatternWell.PAC
{
    /// <summary>
    /// Base class that is implemented by all controllers. This contains all the logic for managing the creation, removal and issuing the request to wire up resources both on the view and the model.
    /// </summary>
    public abstract partial class ControllerBase:NotificationBase,IPacContract
    {
        #region Constructor

        /// <summary>
        /// Constructor for the controller base. this will initialize the unique identifier for the controller.
        /// </summary>
        protected ControllerBase()
        {
            PACId = Guid.NewGuid();
        }

        #endregion
        #region Dispose Implementation - Implementation of the disposal helper method (Do not modify)

        /// <summary>
        /// Helper method that releases resources for this class implementation.
        /// </summary>
        /// <param name="disposed">flag that determines if the class has already been disposed.</param>
        protected override void Dispose(bool disposed)
        {
            ReleaseResourcesForController();
            base.Dispose(disposed);
        }

        #endregion

        #region Release Management - Logic used to release resources for this class (Add release logic in the supplied helper methods)

        /// <summary>
        /// Helper method that releases resource for the 'Controller' class.
        /// </summary>
        private void ReleaseResourcesForController()
        {
            if (this._controlledView != null)
            {
                ReleaseViewResources();
                this._controlledView.ReleaseResources();
                this._controlledView = null;
            }

            if (this._controlledModel == null) return;

            ReleaseModelResources();
            this._controlledModel.ReleaseResources();
            this._controlledModel = null;
        }

        #endregion

        #region Initialization methods for the pac implementation

        /// <summary>
        /// Helper method that will assign a view to be managed by the controller. 
        /// </summary>
        /// <remarks>
        /// You need to make sure the view is already been created before assigning it to the controller.
        /// This helper is to be implemented as a virtual method so you can override, and provide custom implementation if you do not want to simple assign the view to the controller.
        /// </remarks>
        /// <param name="view">The instance of the view cast to the supported view resource interface by this controller.</param>
        protected virtual void AttachViewToController(IViewContract view)
        {
            if(this._controlledView != null)
            {
                try
                {
                    //Releasing the subscription to view based resources
                    this.ReleaseViewResources();
                    this._controlledView.ReleaseResources();
                }
                finally
                {
                    this._controlledView = null;
                }

            }

            this._controlledView = view;
            SubscribeToViewResources();
        }

        /// <summary>
        /// Helper method that will tell the controller to drop all references to the view, and to notify the view to release viewmodel resources.
        /// </summary>
        /// <remarks>
        /// This helper is to be implemented as a virtual method so you can override, and provide custom implementation.
        /// </remarks>
        /// <returns>Returns the refernece to the view that has been detached.</returns>
        protected IViewContract DetachControlledView()
        {
            var currentView = this._controlledView;

            if(this._controlledView != null)
            {
                try
                {
                    this.ReleaseViewResources();
                }
                finally
                {
                    this._controlledView = null;
                }
            }

            return currentView;
        }

        /// <summary>
        /// Helper method that will assign a model to be managed by the controller.
        /// </summary>
        /// <remarks>
        /// You need to make sure the model is already been created before assigning it to the controller.
        /// This helper is to be implemented as a virtual method so you can override, and provide custom implementation if you do not want to simple assign the model to the controller.
        /// </remarks>
        /// <param name="model">The instance of the model cast to the supported model resource interface supported by this controller.</param>
        public virtual void AttachModelToController(IModelContract model)
        {
            if (this._controlledModel != null)
            {
                try
                {
                    //Releasing the subscription to view based resources
                    this.ReleaseModelResources();
                    this._controlledModel.Dispose();
                }
                finally
                {
                    this._controlledModel = null;
                }

            }

            this._controlledModel = model;
            SubscribeToModelResources();
        }

       

        #endregion

        #region Controller managed resources

        /// <summary>
        /// Field that stores the view that is managed by this controller.
        /// </summary>
        protected IViewContract _controlledView = null;


        /// <summary>
        /// Field that stores the model that is managed by this controller.
        /// </summary>
        protected IModelContract _controlledModel = null;


        #endregion

        #region Helper methods that manages subscriptions to controller managed resources.

        /// <summary>
        /// Subscribes to the events and commands that provided in the view contract.
        /// </summary>
        protected virtual void SubscribeToViewResources()
        {
            //nothing is implemented in the base
        }

        /// <summary>
        /// Releases all subscriptions to the views commands and events and data objects provided by the view.
        /// </summary>
        protected virtual void ReleaseViewResources()
        {
            //Nothing is implemented in the base
        }

        /// <summary>
        /// Subscribes to the events that are provided by the model.
        /// </summary>
        protected virtual void SubscribeToModelResources()
        {
            //Nothing is implemented in the base
        }

        /// <summary>
        /// Releases the subscriptions to models events and data objects.
        /// </summary>
        protected virtual void ReleaseModelResources()
        {
            //Nothing is implemented in the base
        }

        #endregion

        #region Implementation of IResource

        /// <summary>
        /// Helper method that polls the resource to determine if it is in a state that it can safely be released.
        /// </summary>
        /// <returns>ReleaseInfo object that holds information if the resource can release, and if it cannot release why it cannot release.</returns>
        public ReleaseInfo CanReleaseResources()
        {
            var releaseInfo = new ReleaseInfo {CanRelease = true};
            if(this._controlledView != null)
            {
                releaseInfo = this._controlledView.CanReleaseResources();

                if(!releaseInfo.CanRelease)
                {
                    return releaseInfo;
                }
            }

            if(this._controlledModel != null)
            {
                releaseInfo = this._controlledModel.CanReleaseResources();
            }

            return releaseInfo;
        }

        /// <summary>
        /// Releases the resources managed by this resource.
        /// </summary>
        public void ReleaseResources()
        {
            this.Dispose();
        }

        #endregion


        #region Implementation of IPacContract

        /// <summary>
        /// Helper method that will call the initialization logic on both the view and the model.
        /// </summary>
        /// <remarks>
        /// This helper method is to be implemented as virtual so you can override and provide custom initialization for the pac related resources as you see fit.
        /// </remarks>
        public virtual void InitializePac()
        {
            if (this._controlledView != null)
            {
                this._controlledView.InitializeView();
            }

            if (this._controlledModel == null) return;

            this._controlledModel.InitializeModel();
        }

        /// <summary>
        /// The unique identifier assigned to the PAC
        /// </summary>
        public Guid PACId { get; private set; }

        #endregion
    }
}
